/**
 * @file drv_flash.h
 * @brief 通用Flash读写驱动头文件
 * @author Claude Code
 * @date 2025-08-09
 * @note 纯驱动层，不包含业务逻辑，易于移植
 */

#ifndef DRV_FLASH_H
#define DRV_FLASH_H

#ifdef __cplusplus
extern "C" {
#endif

/* 确保STM32和HAL库宏定义存在 */
#ifndef USE_HAL_DRIVER
#define USE_HAL_DRIVER
#endif

#ifndef STM32F103xB
#define STM32F103xB
#endif

#include "stm32f1xx_hal.h"
#include <stdint.h>
#include <stdbool.h>

/* ================= 硬件相关配置 (移植时需修改) ================= */

/** @brief Flash页大小 (字节) */
#ifndef DRV_FLASH_PAGE_SIZE
    #ifdef STM32F1xx
        #define DRV_FLASH_PAGE_SIZE         1024    // STM32F1系列页大小1KB
    #elif defined(STM32F4xx)
        #define DRV_FLASH_PAGE_SIZE         16384   // STM32F4系列扇区大小16KB
    #else
        #define DRV_FLASH_PAGE_SIZE         1024    // 默认1KB
    #endif
#endif

/** @brief Flash编程类型 */
#ifndef DRV_FLASH_TYPEPROGRAM
    #ifdef STM32F1xx
        #define DRV_FLASH_TYPEPROGRAM       FLASH_TYPEPROGRAM_HALFWORD
    #elif defined(STM32F4xx)
        #define DRV_FLASH_TYPEPROGRAM       FLASH_TYPEPROGRAM_WORD
    #else
        #define DRV_FLASH_TYPEPROGRAM       FLASH_TYPEPROGRAM_HALFWORD
    #endif
#endif

/* ================= 状态枚举 ================= */

/**
 * @brief Flash驱动状态枚举
 */
typedef enum {
    DRV_FLASH_OK = 0,           ///< 操作成功
    DRV_FLASH_ERROR,            ///< 通用错误
    DRV_FLASH_ERROR_PARAM,      ///< 参数错误
    DRV_FLASH_ERROR_UNLOCK,     ///< 解锁失败
    DRV_FLASH_ERROR_ERASE,      ///< 擦除失败
    DRV_FLASH_ERROR_PROGRAM,    ///< 编程失败
    DRV_FLASH_ERROR_VERIFY,     ///< 校验失败
    DRV_FLASH_ERROR_TIMEOUT     ///< 操作超时
} drv_flash_status_t;

/* ================= 函数声明 ================= */

/**
 * @brief 初始化Flash驱动
 * @retval DRV_FLASH_OK 初始化成功
 * @retval 其他值 初始化失败
 */
drv_flash_status_t drv_flash_init(void);

/**
 * @brief 擦除Flash页
 * @param page_addr 页起始地址，必须页对齐
 * @param page_count 页数量
 * @retval DRV_FLASH_OK 擦除成功
 * @retval 其他值 擦除失败
 */
drv_flash_status_t drv_flash_erase_pages(uint32_t page_addr, uint32_t page_count);

/**
 * @brief 写入数据到Flash
 * @param addr 写入地址
 * @param data 数据指针
 * @param size 数据大小(字节)
 * @retval DRV_FLASH_OK 写入成功
 * @retval 其他值 写入失败
 * @note 写入前必须先擦除对应页
 */
drv_flash_status_t drv_flash_write(uint32_t addr, const void* data, uint32_t size);

/**
 * @brief 从Flash读取数据
 * @param addr 读取地址
 * @param data 数据缓冲区指针
 * @param size 读取大小(字节)
 * @retval DRV_FLASH_OK 读取成功
 * @retval 其他值 读取失败
 */
drv_flash_status_t drv_flash_read(uint32_t addr, void* data, uint32_t size);

/**
 * @brief 写入单个字节
 * @param addr 写入地址
 * @param data 要写入的字节
 * @retval DRV_FLASH_OK 写入成功
 * @retval 其他值 写入失败
 */
drv_flash_status_t drv_flash_write_byte(uint32_t addr, uint8_t data);

/**
 * @brief 写入半字(16位)
 * @param addr 写入地址，必须2字节对齐
 * @param data 要写入的半字
 * @retval DRV_FLASH_OK 写入成功
 * @retval 其他值 写入失败
 */
drv_flash_status_t drv_flash_write_halfword(uint32_t addr, uint16_t data);

/**
 * @brief 写入字(32位)
 * @param addr 写入地址，必须4字节对齐
 * @param data 要写入的字
 * @retval DRV_FLASH_OK 写入成功
 * @retval 其他值 写入失败
 */
drv_flash_status_t drv_flash_write_word(uint32_t addr, uint32_t data);

/**
 * @brief 读取单个字节
 * @param addr 读取地址
 * @retval 读取的字节值
 */
uint8_t drv_flash_read_byte(uint32_t addr);

/**
 * @brief 读取半字(16位)
 * @param addr 读取地址
 * @retval 读取的半字值
 */
uint16_t drv_flash_read_halfword(uint32_t addr);

/**
 * @brief 读取字(32位)
 * @param addr 读取地址
 * @retval 读取的字值
 */
uint32_t drv_flash_read_word(uint32_t addr);

/**
 * @brief 检查Flash页是否已擦除
 * @param page_addr 页起始地址
 * @retval true 页已擦除(全为0xFF)
 * @retval false 页未擦除
 */
bool drv_flash_is_page_erased(uint32_t page_addr);

/**
 * @brief 获取页大小
 * @retval 页大小(字节)
 */
uint32_t drv_flash_get_page_size(void);

/**
 * @brief 获取页起始地址
 * @param addr 任意地址
 * @retval 该地址所在页的起始地址
 */
uint32_t drv_flash_get_page_addr(uint32_t addr);

/**
 * @brief 计算CRC16校验值
 * @param data 数据指针
 * @param size 数据大小
 * @param poly CRC多项式，0表示使用默认值0x1021
 * @retval CRC16校验值
 */
uint16_t drv_flash_calc_crc16(const void* data, uint32_t size, uint16_t poly);

#ifdef __cplusplus
}
#endif

#endif /* DRV_FLASH_H */
